package cn.ciis.basic.kit;

import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;

import java.math.BigInteger;
import java.util.Locale;

/** @author 冉志林 */
public abstract class ByteKit {

  private static final char[] HEX_CHAR = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  };

  /**
   * 将16进制字符串转换为10进制
   *
   * @param bytes
   * @return
   */
  public static String bytesToHexString(byte[] bytes) {
    char[] buf = new char[bytes.length * 2];
    int index = 0;
    // 利用位运算进行转换，可以看作方法一的变种
    for (byte b : bytes) {
      buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
      buf[index++] = HEX_CHAR[b & 0xf];
    }
    return new String(buf);
  }

  /**
   * byte数组转 二进制字符串
   * @param bytes
   * @return
   */
  public static String bytesToBin(byte[] bytes){
    return hex2bin(bytesToHexString(bytes));
  }


  /**
   * 每隔两字符加一个空格
   *
   * @param msg
   * @return
   */
  public static String regex(String msg) {
    String regex = "(.{2})";
    msg = msg.replaceAll(regex, "$1 ");
    return msg;
  }



  /**
   * 计算产生校验码
   *
   * @param data
   * @return
   */
  public static String makeCrc(byte[] data) {
    byte[] buf = new byte[data.length]; // 存储需要产生校验码的数据
    for (int i = 0; i < data.length; i++) {
      buf[i] = data[i];
    }
    int len = buf.length;
    int crc = 0xFFFF; // 16位
    for (int pos = 0; pos < len; pos++) {
      if (buf[pos] < 0) {
        crc ^= (int) buf[pos] + 256; // XOR byte into least sig. byte of
        // crc
      } else {
        crc ^= (int) buf[pos]; // XOR byte into least sig. byte of crc
      }
      for (int i = 8; i != 0; i--) { // Loop over each bit
        if ((crc & 0x0001) != 0) { // If the LSB is set
          crc >>= 1; // Shift right and XOR 0xA001
          crc ^= 0xA001;
        } else {
          crc >>= 1; // Just shift right
        }
      }
    }
    String c = Integer.toHexString(crc);
    if (c.length() == 4) { //
      c = c.substring(2, 4) + c.substring(0, 2);
    } else if (c.length() == 3) {
      c = "0" + c;
      c = c.substring(2, 4) + c.substring(0, 2);
    } else if (c.length() == 2) {
      c = "0" + c.substring(1, 2) + "0" + c.substring(0, 1);
    }
    return c;
  }

  /**
   * 16进制解析为10进制(按16进制方式)
   *
   * @param str 16进制转为的10进制数据包
   * @param begin 截取字符串的开始
   * @param end 截取字符串的结束
   * @return
   */
  public static String hexToString(String str, int begin, int end) {
    return hexStr2Str(str.substring(begin * 2, end * 2));
  }


  /**
   * 将int类型数据转为1字节的16进制 
   * @Title: hex4Dec 
   * @Description: 将int类型数据转为1字节的16进制
   * @param: @param
   * num @param: @return @return: String @throws
   */
  public static String hex2Dec(int num) {

    String a = Integer.toHexString(num);
    while (a.length() <= 1) {
      a = String.format("0%s", a);
    }
    return a;
  }

  /**
   * 将int类型数据转为2字节的10进制 
   * @Title: hex4Dec 
   * @Description: 将int类型数据转为2字节的10进制 
   * @param: @param
   * num @param: @return @return: String @throws
   */
  public static String hex4Dec(int num) {
    String a = Integer.toHexString(num);
    while (a.length() <= 3) {
      a = String.format("0%s", a);
    }
    return a;
  }

  /**
   * 16进制转byte数组
   *
   * @param src
   * @return
   */
  public static byte[] hexStr2Bytes(String src) {
    /*对输入值进行规范化整理*/
    src = src.trim().replace(" ", "").toUpperCase(Locale.US);
    // 处理值初始化
    int m = 0, n = 0;
    int iLen = src.length() / 2; // 计算长度
    byte[] ret = new byte[iLen]; // 分配存储空间

    for (int i = 0; i < iLen; i++) {
      m = i * 2 + 1;
      n = m + 1;
      ret[i] = (byte) (Integer.decode("0x" + src.substring(i * 2, m) + src.substring(m, n)) & 0xFF);
    }
    return ret;
  }

  /**
   * 格式化16进制字符串时间
   *
   * @param time
   */
  public static String formatTime(String time) {
    String substring = "";
    for (int i = 0; i < time.length(); i += 2) {
      String subs = new BigInteger(time.substring(i, 2 + i), 16).toString();
      if (i == 0) {
        substring += Integer.parseInt(subs) + 2000;
      } else if (i > 0 && i < 5) {
        substring += "-" + subs;
      } else if (i > 7) {
        substring += ":" + subs;
      } else {
        substring += " " + subs;
      }
    }
    return substring;
  }


  /**
   * 16进制直接转换成为字符串(无需Unicode解码)
   *
   * @param hexStr
   * @return
   */
  public static String hexStr2Str(String hexStr) {
    String str = "0123456789ABCDEF";
    char[] hexs = hexStr.toCharArray();
    byte[] bytes = new byte[hexStr.length() / 2];
    int n;
    for (int i = 0; i < bytes.length; i++) {
      n = str.indexOf(hexs[2 * i]) * 16;
      n += str.indexOf(hexs[2 * i + 1]);
      bytes[i] = (byte) (n & 0xff);
    }
    return new String(bytes);
  }

  /**
   * 16进制转位2进制的字符串
   * @param hexString
   * @return
   */
  public static String hex2bin(String hexString) {
    if (hexString == null || hexString.length() % 2 != 0)
      return null;
    String bString = "", tmp;
    for (int i = 0; i < hexString.length(); i++) {
      tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
      bString += tmp.substring(tmp.length() - 4);
    }
    return bString;
  }

  /**
   * 2进制的字符串转16进制字符串
   * @param bString
   * @return
   */
  public static String bin2hex(String bString) {
    if (bString == null || bString.equals("") || bString.length() % 8 != 0)
      return null;
    StringBuffer tmp=new StringBuffer();
    int iTmp = 0;
    for (int i = 0; i < bString.length(); i += 4) {
      iTmp = 0;
      for (int j = 0; j < 4; j++) {
        iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1);
      }
      tmp.append(Integer.toHexString(iTmp));
    }
    return tmp.toString();
  }

  /**
   * 10进制数字转换成16进制字符串
   * @param num 要转换的数字
   * @param length 需要占用的字节数。不够会自动补0
   * @return
   */
  public static String DecToHexString(int num, int length){

    String result = Integer.toHexString(num);
    int zero_count = length*2-result.length();

    if(zero_count>0){
      StrBuilder builder = new StrBuilder("");
      for (int i = 0; i < zero_count; i++) {
        builder.append("0");
      }
      return StrUtil.format("{}{}", builder.toString(), result);
    }
    return  result;
  }

  /**
   * 亦或检验  返回为16进制的字符串数据
   * @param head  需要与谁开始
   * @param hexStr 16进制的数据字符串
   * @return
   */
  public static String getXor(byte head,String hexStr){
    byte[] data=ByteKit.hexStr2Bytes(hexStr);
    for (int i = 0; i <data.length; i++) {
      head ^=data[i];
    }
    String str = Integer.toHexString(Integer.valueOf(head));
    if (str.length()>2){
      str=str.substring(str.length()-2);
    }
    return str;
  }
}
